#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include "global.h"
#include "md5.h"

#define MD5_CTX MD5_CTX
#define MDInit MD5Init
#define MDUpdate MD5Update
#define MDFinal MD5Final
#define MD 5

/* Prints a message digest in hexadecimal.*/
static void MDPrint (digest)
unsigned char digest[16];
{
 	unsigned int i;
	for(i = 0; i < 16; i++)
	{
		printf ("%02x", digest[i]);
	}
}

/* Digests a file and prints the result.*/
static void MDFile (filename)
char *filename;
{
  	FILE *file;
	MD5_CTX context;
	int len;
	unsigned char buffer[1024], digest[16];

	if ((file = fopen (filename, "rb")) == NULL)
	{
		printf ("%s can't be opened\n", filename);
	}
	else 
	{
		MDInit (&context);
		while (len = fread(buffer, 1, 1024, file)) 
		{
			MDUpdate (&context, buffer, len);
		}
		MDFinal (digest, &context);

		fclose (file);

		printf ("MD%d (%s) = ", MD, filename);
		MDPrint (digest);
	printf ("\n");
	}
}

/* do md5 hash alg in linear*/
int linear(int argc, char **argv)
{
	int i;
	for(i=2; i<argc; i++)
	{
		MDFile(argv[i]);	
	}
	return 0;
}

/* Created Thread - calls md5 alg */
void *md5Thread(void *arg)
{
	char *filename;
	filename = (char *) arg;
	MDFile(filename);
}

/* do md5 hash alg in parallel*/
int parallel(int argc, char **argv)
{
	pthread_t flows[argc-2];
	int i;
	for(i=0; i<argc-2; i++)
	{
		int t;
		t = pthread_create(&flows[i], NULL, md5Thread, argv[i+2]);
		if(t)
		{
			printf("ERROR creating thread\n");
		}
	}
	for(i=0; i<argc-2; i++)
	{
		pthread_join(flows[i], NULL);
	}
	return 0;
}

int main(int argc, char *argv[])
{
	if(argc <=2)
	{
		printf("please enter a '-l' or '-p' flag as well as a filename\n");
		return 0;
	}
	if( (strcmp(argv[1], "-l") == 0) || (strcmp(argv[1], "-p") == 0) )
	{
		if(strcmp(argv[1], "-l") == 0)
		{
			linear(argc, argv);
		}
		else
		{
			parallel(argc, argv);
		}
	}
	else
	{
		printf("please enter a '-l' or '-p' flag\n");
		return 0;
	}
	
	return 0;
}